﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SmartMathLibrary.Geometry
{
    /// <summary>
    /// This class describes a circle in a plane space.
    /// </summary>
    [Serializable]
    public class Circle : ICircle
    {
        /// <summary>
        /// The radius of the circle.
        /// </summary>
        private double radius;

        /// <summary>
        /// The center of the circle.
        /// </summary>
        private Point2D center;

        /// <summary>
        /// Initializes a new instance of the <see cref="Circle"/> class.
        /// </summary>
        /// <param name="radius">The radius of the circle.</param>
        public Circle(double radius)
        {
            this.radius = radius;
            this.center = new Point2D();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Circle"/> class.
        /// </summary>
        /// <param name="circle">The circle to clone.</param>
        public Circle(Circle circle)
        {
            if (circle == (Circle) null)
            {
                throw new ArgumentNullException("circle");
            }

            this.radius = circle.Radius;
            this.center = circle.Center;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Circle"/> class.
        /// </summary>
        /// <param name="radius">The radius of the circle.</param>
        /// <param name="center">The center of the circle.</param>
        public Circle(double radius, Point2D center)
        {
            if (center == (Point2D) null)
            {
                throw new ArgumentNullException("center");
            }

            this.radius = radius;
            this.center = center;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Circle"/> class.
        /// </summary>
        /// <param name="radius">The radius of the circle.</param>
        /// <param name="x">The x position of the circle.</param>
        /// <param name="y">The y position of the circle.</param>
        public Circle(double radius, double x, double y)
        {
            this.radius = radius;
            this.center = new Point2D(x, y);
        }

        /// <summary>
        /// Gets or sets the radius of the circle.
        /// </summary>
        /// <value>The radius of the circle.</value>
        public double Radius
        {
            get { return radius; }
            set { radius = value; }
        }

        /// <summary>
        /// Gets or sets the center of the circle.
        /// </summary>
        /// <value>The center of the circle.</value>
        public Point2D Center
        {
            get { return center; }
            set { center = value; }
        }

        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="a">The first circle.</param>
        /// <param name="b">The second circle.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator ==(Circle a, Circle b)
        {
            if (System.Object.ReferenceEquals(a, b))
            {
                return true;
            }

            if (((object) a == null) || ((object) b == null))
            {
                return false;
            }

            return ((a.Center == b.Center) && (a.Radius == b.Radius));
        }

        /// <summary>
        /// Implements the operator !=.
        /// </summary>
        /// <param name="a">The first circle.</param>
        /// <param name="b">The second circle.</param>
        /// <returns>The result of the operator.</returns>
        public static bool operator !=(Circle a, Circle b)
        {
            return !(a == b);
        }

        /// <summary>
        /// Compares the current instance of a circle with another circle.
        /// </summary>
        /// <param name="compare">The circle to compare.</param>
        /// <returns>True if the position and the radius are even otherwise, false.</returns>
        public bool CompareTo(Circle compare)
        {
            if (compare != (Circle) null)
            {
                throw new ArgumentException("compare != (Circle)null", "compare");
            }

            if (compare == (Circle) null)
            {
                throw new ArgumentNullException("compare");
            }

            return this == compare;
        }

        /// <summary>
        /// Translates the position of the circle with a specified value.
        /// </summary>
        /// <param name="translateValue">The translation value for the x and y position.</param>
        public void TranslateCircle(double translateValue)
        {
            this.center.TranslateTransformation(translateValue);
        }

        /// <summary>
        /// Translates the position of the circle with a specified value.
        /// </summary>
        /// <param name="translateValueX">The translation value for the x position.</param>
        /// <param name="translateValueY">The translation value for the y position.</param>
        public void TranslateCircle(double translateValueX, double translateValueY)
        {
            this.center.TranslateTransformation(translateValueX, translateValueY);
        }

        /// <summary>
        /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
        /// <returns>
        /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
        /// </returns>
        /// <exception cref="T:System.NullReferenceException">The <paramref name="obj"/> parameter is null.</exception>
        public override bool Equals(object obj)
        {
            return base.Equals(obj);
        }

        /// <summary>
        /// Serves as a hash function for a particular type.
        /// </summary>
        /// <returns>
        /// A hash code for the current <see cref="T:System.Object"/>.
        /// </returns>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        /// <summary>
        /// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
        /// </returns>
        public override string ToString()
        {
            return "Radius = " + this.radius.ToString() + " Center = " + this.center.ToString();
        }
    }
}